/**
 * Created by Admin on 13.02.2015.
 */

(function ($) {
    window.GlMouseControl = $.inherit({
        gl: null,
        canvas: null,
        sceneObjects: [],
        currentRIndex: 0,
        currentGIndex: 0,
        currentBIndex: 0,
        currentAIndex: 0,
        currentObject: null,

        forceRefresh: function () {
            var e = this.currentE;
            if (!e) return;
            this.isClick = true;
            $.each(this.shaderControls, function (_, shaderControl) {
                shaderControl.render(function (sceneObject) {
                    sceneObject.isClick = true;
                }, function (sceneObject) {
                    sceneObject.isClick = false;
                })
            });
            var rgba = this.requestPixelHandler(e);
            var control = this;
            this.getObject(rgba, function (sceneObjects, rgba) {
                control.currentObject = rgba && sceneObjects[rgba[0]][rgba[1]][rgba[2]][rgba[3]];
            }, function () {
                control.currentObject = null;
            });
            this.isClick = false;
        },

        initializeListening: function () {
            var canvas = this.canvas;
            var control = this;
            var interval;
            var updateEvent = function (e) {
                control.currentE = e;

            };
            return $(canvas).bind("mouseenter", function () {
                $(this).bind("mousemove", updateEvent);
                interval = setInterval(function () {
                    control.forceRefresh();
                }, 100);

            }).bind("mouseleave", function () {
                $(this).unbind("mousemove", updateEvent);
                clearInterval(interval);
            });
        },

        __constructor: function (gl, canvas, shaderControls) {
            this.gl = gl;
            this.canvas = canvas;
            this.isClick = false;
            this.shaderControls = shaderControls;
            this.initializeListening(canvas);

        },

        requestPixelHandler: function (e) {
            var res = new Uint8Array(4);
            var gl = this.gl;
            var x = e.clientX;
            var y = this.canvas.height - e.clientY;
            gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, res);
            return res
        },

        addClickableObject: function (sceneObject, objectId) {
            this.addObject(sceneObject);
        },

        _increaseIndex: function () {
            this.currentAIndex++;
            if (this.currentAIndex == 256) {
                this.currentBIndex++;
                if (this.currentBIndex == 256) {
                    this.currentGIndex++;
                    if (this.currentGIndex == 256) {
                        this.currentRIndex++;
                        this.currentGIndex = 0;
                    }
                    this.currentBIndex = 0;
                }
                this.currentAIndex = 0;
            }
        },

        getObject: function (rgba, callback, noObject, create) {
            callback = callback || $.noop;
            noObject = noObject || $.noop;
            var rIndex = rgba[0];
            var r = this.sceneObjects[rIndex];
            if (!r && create) {
                r = [];
                this.sceneObjects[rIndex] = r;
            }

            var gIndex = rgba[1];
            var g = r && r[gIndex];
            if (!g && create) {
                g = [];
                r[gIndex] = g;
            }

            var bIndex = rgba[2];
            var b = g && g[bIndex];
            if (!b && create) {
                b = [];
                g[bIndex] = b;
            }

            var aIndex = rgba[3];
            var a = b && b[aIndex];
            if (!a && create) {
                a = [];
                b[aIndex] = a;
            }

            r && g && b && a ? callback(this.sceneObjects, rgba) : noObject();
        },

        handleSceneObject: function (sceneObject, eventHandlers, e) {
            return eventHandlers && $.each(eventHandlers, function (_, func) {
                    func(sceneObject, e);
                });
        },
        addObject: function (sceneObject) {
            this._increaseIndex();
            this.getObject([
                    this.currentRIndex,
                    this.currentGIndex,
                    this.currentBIndex,
                    this.currentAIndex],
                function (sceneObjects, rgba) {
                    sceneObjects[rgba[0]][rgba[1]][rgba[2]][rgba[3]] = sceneObject;
                    sceneObject.rgba = rgba;
                }, null, true);
            var control = this;
            var handlers = sceneObject.handlers;
            handlers && $.each(handlers, function (event, eventHandlers) {
                $(control.canvas).bind(event, function (e) {
                    sceneObject == control.currentObject && control.handleSceneObject(sceneObject, eventHandlers, e)
                })
            })
        }

    })
})(window["jQuery"]);